package cn.xorange.commons.data.entity;

import cn.xorange.commons.data.constants.QueryType;
import cn.xorange.commons.data.utils.ParamUtil;
import cn.xorange.commons.datasource.configuration.MyBatisConfig;
import cn.xorange.commons.datasource.configuration.MyBatisProperties;
import cn.xorange.commons.utils.spring.SpringUtils;
import org.apache.commons.lang3.ObjectUtils;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.*;

/**
 * Where 方法类
 * 这里的where  生成的Param只接受参数，到whereBuild中再次进行封装
 * @author yj
 */
public class Where implements Serializable {
    public Where(Class<?> beanClass){
        this.paramList = new ArrayList<>();
        this.beanClass = beanClass;
        this.isMapUnderscoreToCamelCase = SpringUtils.getBean(MyBatisProperties.class).mapUnderscoreToCamelCase;
    }

    private final boolean isMapUnderscoreToCamelCase;

    private final Class<?> beanClass;
    private final List<Param> paramList;
    public List<Param> getParamList(){
        return this.paramList;
    }



    public void equal(String fieldName, Object value){
        this.listAddParam(fieldName,value, QueryType.EQUAL);
    }
    public void equal(String fieldName, String colName, Object value){
        this.listAddParam(fieldName,colName, value, QueryType.EQUAL);
    }

    public void notEqual(String fieldName, Object value){
        this.listAddParam(fieldName,value,QueryType.NOTEQUAL);
    }
    public void notEqual(String fieldName, String colName,  Object value){
        this.listAddParam(fieldName,colName, value,QueryType.NOTEQUAL);
    }

    public void between(String fieldName,Object val1,Object val2){
        gte(fieldName,val1);
        lt(fieldName,val2);
    }


    /** > */
    public void gt(String fieldName, Object value){
        this.listAddParam(fieldName,value,QueryType.GT);
    }

    public void gt(String fieldName,String colName, Object value){
        this.listAddParam(fieldName, colName, value, QueryType.GT);
    }
    /** >= */
    public void gte(String fieldName, Object value){
        this.listAddParam(fieldName,value,QueryType.GTE);
    }
    public void gte(String fieldName,String colName, Object value){
        this.listAddParam(fieldName, colName, value,QueryType.GTE);
    }
    /** < */
    public void lt(String fieldName, Object value){
        this.listAddParam(fieldName,value,QueryType.LT);
    }
    public void lt(String fieldName,String colName, Object value){
        this.listAddParam(fieldName, colName, value,QueryType.LT);
    }
    /** <= */
    public void lte(String fieldName, Object value){
        this.listAddParam(fieldName,value,QueryType.LTE);
    }
    public void lte(String fieldName,String colName, Object value){
        this.listAddParam(fieldName,colName, value,QueryType.LTE);
    }
    public void leftLike(String fieldName, Object value){
        this.listAddParam(fieldName,value,QueryType.LEFTLIKE);
    }
    public void leftLike(String fieldName,String colName, Object value){
        this.listAddParam(fieldName, colName, value,QueryType.LEFTLIKE);
    }
    public void rightLike(String fieldName, Object value){
        this.listAddParam(fieldName,value,QueryType.RIGHTLIKE);
    }
    public void rightLike(String fieldName,String colName, Object value){
        this.listAddParam(fieldName,colName, value,QueryType.RIGHTLIKE);
    }
    public void like(String fieldName, Object value){
        this.listAddParam(fieldName,value,QueryType.LIKE);
    }
    public void like(String fieldName,String colName, Object value){
        this.listAddParam(fieldName, colName, value,QueryType.LIKE);
    }

    public void in(String fieldName, Collection values){
        this.in(fieldName,null,values);
    }

    public void in(String fieldName, String colName, Collection values){
        if(Objects.nonNull(values) && !values.isEmpty()){
            Set<Object> set = new HashSet<>(values);
            if(Objects.nonNull(colName)){
                this.listAddParam(fieldName, colName, set, QueryType.IN);
            }else {
                this.listAddParam(fieldName, set, QueryType.IN);
            }
        }


    }

    public void in(String fieldName, Object[] values){
        this.in(fieldName,null, values);
    }
    public void in(String fieldName, String colName, Object[] values){

        if (Boolean.TRUE.equals(ObjectUtils.isNotEmpty(values))){
            Set<Object> set = new HashSet<>(Arrays.asList(values));
            if(Objects.isNull(colName)){
                this.listAddParam(fieldName,set,QueryType.IN);
            }else {
                this.listAddParam(fieldName,colName, set,QueryType.IN);
            }
        }
    }


    public void notIn(String fieldName, Collection<Object> values){
        this.in(fieldName,null,values);
    }
    public void notIn(String fieldName, String colName, Collection<Object> values){
        if(Objects.nonNull(values) && !values.isEmpty()){
            Set<Object> set = new HashSet<>(values);
            if(Objects.nonNull(colName)){
                this.listAddParam(fieldName, colName, set, QueryType.NOTIN);
            }else {
                this.listAddParam(fieldName, set, QueryType.NOTIN);
            }
        }


    }
    public void notIn(String fieldName, Object... values){
        this.in(fieldName,null, values);
    }
    public void notIn(String fieldName, String colName, Object... values){
        if (Boolean.TRUE.equals(ObjectUtils.isNotEmpty(values))){
            Set<Object> set = new HashSet<>(Arrays.asList(values));
            if(Objects.isNull(colName)){
                this.listAddParam(fieldName,set,QueryType.NOTIN);
            }else {
                this.listAddParam(fieldName,colName, set,QueryType.NOTIN);
            }
        }
    }




    public void isNull(String fieldName){
        this.listAddParam(fieldName,"",QueryType.ISNULL);
    }
    public void isNull(String fieldName,String colName){
        this.listAddParam(fieldName, colName,"",QueryType.ISNULL);
    }

    public void isNotNull(String fieldName){
        this.listAddParam(fieldName,"",QueryType.ISNOTNULL);
    }
    public void isNotNull(String fieldName,String colName){
        this.listAddParam(fieldName,colName,"",QueryType.ISNOTNULL);
    }

    private void listAddParam(String fieldName, Object value,String queryType){
        Field field = ParamUtil.getField(beanClass, fieldName);
        String colName = ParamUtil.getColName(field,isMapUnderscoreToCamelCase);
        paramList.add(new Param(fieldName,colName,queryType,value));
    }

    private void listAddParam(String fieldName, String colName, Object value,String queryType){
        paramList.add(new Param(fieldName,colName,queryType,value));
    }

    //private void listAddNullParam(String fieldName,String queryType){
    //    Field field = ParamUtil.getField(t,fieldName);
    //    MColumn mColumn = field.getAnnotation(MColumn.class);
    //    if(ObjectUtils.isNotEmpty(field)
    //            && ObjectUtils.isNotEmpty(fieldName)){
    //        paramList.add(Param.whereParam(field,mColumn,queryType,null,isMapUnderscoreToCamelCase));
    //    }
    //}

}
